[Rust] bitflagsマクロでビットフラグ管理
Introduction
bitflagsはビットフラグを簡単に定義することができるマクロを
提供してくれるcrateです。
複数のフラグ管理をシンプルにしてくれます。
Environment
- MacBook Pro (13-inch, M1, 2020)
- OS : MacOS 11.3.1
- rust : 1.60.0
Try
cargo new でプロジェクトをつくったら
Cargo.tomlに依存ライブラリを記述します。
[dependencies] bitflags = "1.3.2"
マクロ(bitflags!)をつかって複数のフラグを管理する構造体として定義します。
↓ではu32型の変数1つでA,B,Cの3つのフラグを管理します。
use bitflags::bitflags; bitflags! { pub struct Flags: u32 { const A = 0b00000001; const B = 0b00000010; const C = 0b00000100; } }
普通に変数に代入して比較したり、
containsで対象のフラグが含まれているかチェックできます。
let flag = Flags::A; assert_eq!(flag, Flags::A); assert_eq!(flag.contains(Flags::A), true);
複数のフラグもセットできます。
それぞれの変数で&をとったり引き算したりできます。
//複数フラグセット let flag_1 = Flags::A | Flags::C; let flag_2 = Flags::B | Flags::C; assert_eq!((flag_1 & flag_2), Flags::C); assert_eq!((flag_1 -flag_2), Flags::A); assert_eq!(!flag_2, Flags::A);
実際の値を表示するにはbitsを使いましょう。
println!("{:#010b}", Flags::A.bits);// 0b00000001 println!("{:#010b}", Flags::B.bits);// 0b00000010 println!("{:#010b}", Flags::C.bits);// 0b00000100 println!("{:#010b}", flag.bits);//0b00000001 println!("{:#010b}", flag_1.bits);//0b00000101 println!("{:#010b}", flag_2.bits);//0b00000110
removeとinsertでフラグの変更。
let mut flag:Flags = Flags::A; assert_eq!(flag, Flags::A); flag = Flags::A | Flags::C; assert_eq!(flag, Flags::A | Flags::C); assert_eq!(flag & Flags::A, Flags::A); assert_eq!(flag & Flags::C, Flags::C); //remove flag.remove(Flags::C); assert_eq!(flag.contains(Flags::A), true); assert_eq!(flag.contains(Flags::B), false); assert_eq!(flag.contains(Flags::C), false); //insert flag.insert(Flags::C); assert_eq!(flag.contains(Flags::A), true); assert_eq!(flag.contains(Flags::B), false); assert_eq!(flag.contains(Flags::C), true);
all関数ですべてのフラグをたてることができる。
let all_flag = Flags::all(); println!("{:#010b}", all_flag.bits);//0b00000111
簡単な説明は以上です。
これ以外にも機能があるので、ドキュメントをご確認ください。
Summary
bitflagsマクロを使うと、普通にやるよりシンプルにフラグ管理ができます。
boolで8つのフラグを構造体で定義したら8bit必要ですが、
bitflagsでu32のフラグを使えば4bitで管理できます。
無駄なリソースも使わず、安全に計算できたりもするので楽ですね。